package cachee

import (
	"context"
	"time"

	"golang.org/x/sync/singleflight"
)

var sg singleflight.Group

type KvItem[V any] struct {
	store KvStore[string, V]

	Key        string
	Expiration time.Duration

	Load func() (V, error)
}

func (item *KvItem[V]) GetOrLoad(ctx context.Context) (v V, err error) {

	if item.Expiration < 1 {
		return item.Load()
	}

	v, exist, err := item.getStore().Get(ctx, item.Key)
	if exist {
		return
	}

	flight := false
	vi, err, _ := sg.Do(item.Key, func() (interface{}, error) { flight = true; return item.Load() })
	if err != nil {
		return
	}

	v = vi.(V)

	if flight {
		err = item.getStore().Set(ctx, item.Key, v, item.Expiration)
		if err != nil {
			return
		}
	}

	return
}

func (item *KvItem[V]) getStore() KvStore[string, V] {
	return item.store
}
